#include "CMainWindow.h"

#include <QHBoxLayout>
#include <QMap>
#include <QMessageBox>
#include <QPushButton>

#include "QProperty.h"
#include "QNumberProperty.h"
#include "QBoolProperty.h"
#include "QFileProperty.h"
#include "QColorProperty.h"
#include "QVector3DProperty.h"
#include "QShortcutProperty.h"

using namespace QPE;

// The default constructor just sets up the window
CMainWindow::CMainWindow(QWidget *parent) :
	QMainWindow(parent)
{
	// First, we create the Property Model and add the main window as parent, so that the model gets deleted when this window does.
	PropertyModel = new QPropertyModel(this);

	// Then we create the tree view displaying the properties and give it our model.
	// We could also use the other constructor not passing a QPropertyMoedl and later set it like
	// usual with TreeView->setModel();
	TreeView = new QPropertyTreeView(PropertyModel, this);

	TreeView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

	// Let's setup the main window
	setCentralWidget(new QWidget(this));
	setWindowTitle(tr("Example 1: Getting started (QtPropertyExplorer)"));

	// Now we create a layout to have a nicer look and add the tree view
	QHBoxLayout* layout = new QHBoxLayout(this);
	centralWidget()->setLayout(layout);
	layout->setSpacing(5);
	layout->setMargin(0);
	layout->addWidget(TreeView);

	/* What we now have is a main window as usual, with a tree view inside.
		So far, so good. Next step would be to populate the Property Model with properties.
		Basically, we can just create a new QProperty-object, that can handle pretty much
		everything that QVariant can handle. Note that the name (passed in the constructor
		of QProperty)of the property is what is displayed on the left side of the property
		browser, not an identifier. Thus it should get translated, if you plan to use localozation. */
	QProperty* tmpProp = new QProperty(tr("TestString"));
	tmpProp->setValue("This is a test string");

	// Now we need to add the property to the model. When doing that, we give it an unique id
	// in form of a string, so that we can identify the property later on:
	PropertyModel->addProperty(tmpProp, "String1");

	/* If we would run this example now, we'd get a property browser with one property.

	Although the base class implementation of QProperty works pretty well already,
	some data types need some additional features. For instance, we could create an integer
	with the standard implementation of QProperty: */
	tmpProp = new QProperty(tr("Lame Integer"));
	tmpProp->setValue(42);
	PropertyModel->addProperty(tmpProp, "Integer1");

	/* As you can see, a nice QSpinBox gets created by the standard editor factory and sometimes
	this is enough. But sometimes it also would be nice to be able to set some additional options,
	like a minimum or maximum value and the number of decimals in case of an floating point
	number.
	For this reason, QPE comes with a set of standard implementations of QProperty that provide
	this additional features. In case of an integer or a double value, it would work this way: */

	QIntegerProperty* tmpIntProp = new QIntegerProperty(tr("Cool Integer"));
	tmpIntProp->setValue(42);
	tmpIntProp->setSettings(0, 100);
	PropertyModel->addProperty(tmpIntProp, "Integer2");

	QDoubleProperty* tmpDoubleProp = new QDoubleProperty(tr("Cool Double"));
	tmpDoubleProp->setValue(12.341);
	tmpDoubleProp->setSettings(0, 100, 3);
	PropertyModel->addProperty(tmpDoubleProp, "Double1");

	/* As you can see, both property classes (QIntegerProperty and QDoubleProperty) provide
	a function setSettings(), with which we can set the minimum and maximun and, in case of the
	double property, the precision.

	Sometimes your application has certain requirements for a property, such as the minimum or
	maximum, but you don't know what kind of property you are dealing with. Of course you could try
	to find out by using a big switch(...) { case... } construction, but there might be an easier way:

	It is possible to give a property a set of settings without knowing what those settings contain.
	QProperty provides an (empty) standard implementation of setSettings(), that takes a QMap as argument.
	This way, subclasses can reimplement this function and we can use it as follows: */
	tmpProp = new QIntegerProperty(tr("Another Integer"));
	PropertyModel->addProperty(tmpProp, "Integer3");
	QMap<QString, QVariant> exampleSettings;
	exampleSettings.insert("Min", -10);
	exampleSettings.insert("Max", 10);
	tmpProp->setSettings(exampleSettings);

	/* Now let's see how we can interact with the QPropertyModel. The following code shows,
	how to get properties from a model as well as use the model's signals: */
	connect(PropertyModel, SIGNAL(onDataChangedByEditor(QProperty*)), this, SLOT(userChangedData(QProperty*)));
	// See userChangedData(QProperty *prop)-implementation for more details.

	/* Last but not least, let's just fill the property browser with some more properties of different
	types so that we have something to play with :)*/
	tmpProp = new QBoolProperty(tr("Boolean"));
	tmpProp->setValue(true);
	PropertyModel->addProperty(tmpProp, "Bool1");

	tmpProp = new QShortcutProperty(tr("A key sequence"));
	PropertyModel->addProperty(tmpProp, "Shortcut");

	tmpProp = new QColorProperty(tr("Color"));
	tmpProp->setValue(QColor(255, 0, 0));
	PropertyModel->addProperty(tmpProp, "Color1");

	QFileProperty* tmpFileProp = new QFileProperty(tr("Image File"));
	tmpFileProp->setFileFilters(tr("Image Files (*.png *.jpg *.bmp *.jpeg *.tif *.tga)"));
	PropertyModel->addProperty(tmpFileProp, "ImageFile1");

	QVector3DProperty* tmpVectProp = new QVector3DProperty(tr("3D-Vector"));
	tmpVectProp->setVector(10, 20, 30);
	PropertyModel->addProperty(tmpVectProp, "Vector1");

	tmpProp = new QColorProperty(tr("Another Color"));
	tmpProp->setValue(QColor(255, 0, 0));
	PropertyModel->addProperty(tmpProp, "Color2");

	tmpFileProp = new QFileProperty(tr("Text File"));
	tmpFileProp->setFileFilters(tr("Text Files (*.txt)"));
	PropertyModel->addProperty(tmpFileProp, "TextFile1");

	tmpVectProp = new QVector3DProperty(tr("Another 3D-Vector"));
	tmpVectProp->setVector(10, 20, 30);
	PropertyModel->addProperty(tmpVectProp, "Vector2");

}

CMainWindow::~CMainWindow()
{
	// We don't need to do anything in the destructor
}

void CMainWindow::userChangedData(QProperty *prop)
{
	if(!prop)
		return;

	/* What we want to do here, is to annoy the user a bit: He get's to see a message-box
	every time he changes a property. */

	QMessageBox tmpMessageBox(QMessageBox::Information, "Information",
					tr("You, Sir, have changed the property %1 to the new value %2").arg(prop->getName(), prop->data(QProperty::DPC_Data).toString()),
					QMessageBox::Ok, this);

	QAbstractButton* tmpButton = tmpMessageBox.addButton("Ok, now let me alone!", QMessageBox::ActionRole);
	tmpMessageBox.exec();
	QAbstractButton* tmpButton2 = tmpMessageBox.clickedButton();

	// ...if the user has enough, then let's leave him alone.
	if(tmpButton2 == tmpButton)
		disconnect(PropertyModel, 0, this, 0);
}
